package com.jj.net.tcp;

import ch.qos.logback.core.net.server.ServerListener;
import com.jj.config.Constants;
import com.jj.net.codec.UserMessageCodec;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * Copyrights: QidianGroup@JJ
 *
 * @author: LuHan
 * @date: 2018/1/15, 14:19
 */
@ConfigurationProperties("tcp")
@Component
public class TcpAccepterManager {
    private static Logger logger = LoggerFactory.getLogger(TcpAccepterManager.class);

    private String host;
    private int port;

    private EventLoopGroup bossGroup= null;
    private EventLoopGroup workerGroup = null;

    @Autowired
    private TcpChannelListener tcpChannelListener;


    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    {
        logger.debug("TCPAcceptorManager has been created!");
    }

    public boolean start() {
        logger.debug("start TCPAcceptorManager {}:{}", host, port);
        bossGroup = new NioEventLoopGroup(1);
        workerGroup = new NioEventLoopGroup(1);
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() { // (4)
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ch.config().setAllocator(PooledByteBufAllocator.DEFAULT);

                            ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
                            ch.pipeline().
                                    addLast(
                                            new LengthFieldBasedFrameDecoder(
                                                    Constants.MAX_PACKAGE_LENGTH,
                                                    0,4,-4,4)
                                    );
                            ch.pipeline().addLast(new LengthFieldPrepender(4, true));
                            //ch.pipeline().addLast(new EnigmaHandler());
                            ch.pipeline().addLast(new UserMessageCodec());
                            ch.pipeline().addLast(new GameIOHandler(tcpChannelListener));
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            // Bind and start to accept incoming connections.
            logger.debug("prepare to listen on {}", port);
            ChannelFuture f = b.bind(port).sync();
        }catch (Throwable t){
            logger.error("exception", t);
        }
        return false;
    }

    public boolean stop() {
        return false;
    }
}
